<template>
  <div class="pad-t-40" v-loading="saveLoading">
    <el-steps class="pad-lr-20 mar-b-40" :active="stepActive - 1" finish-status="success">
      <el-step v-for="step in steps" :title="step" :key="step"></el-step>
    </el-steps>
    <el-container style="height: 400px">
      <el-aside class="h-100p bor-r" style="width: 200px" :class="{'hidden': stepActive > 1}">
        <el-tree ref="tableNameTree" node-key="id" element-loading-text="正在加载中..." v-loading="treeLoading" :accordion="true" :data="tableNamesData" @node-click="handleNodeClick"></el-tree>
      </el-aside>

      <el-main class="h-100p pad-lr-20" :class="{'hidden': stepActive > 1}">
        <el-table ref="multipleTable" height="400" stripe :data="tableData" v-loading="tableLoading" @selection-change="handleSelectionChange">
          <el-table-column type="selection" width="55"></el-table-column>
          <el-table-column property="name" label="字段名称" width="150"></el-table-column>
          <el-table-column property="type" label="类型" width="200"></el-table-column>
          <el-table-column property="comment" label="注解"></el-table-column>
        </el-table>
      </el-main>

      <el-main class="h-100p pad-lr-20" v-if="stepActive === 2">
        <el-row :gutter="20">
          <el-col class="lh-40 bg-gray-4" :span="10">名称</el-col>
          <el-col class="lh-40 bg-gray-4" :span="4">类型</el-col>
          <el-col class="lh-40 bg-gray-4" :span="10">规则</el-col>
        </el-row>
        <el-row class="bor-b mar-t-10" v-for="item in tableSelectData" :gutter="20" :key="item.index">
          <el-col :span="10" class="lh-36"><span class="text-red">*</span> {{item.name}}</el-col>
          <el-col :span="4" class="lh-36">{{item.type}}</el-col>
          <el-col :span="10">
            <el-select class="dis-b" size="medium" clearable multiple @change="ruleCahnge" v-model="ruleMaps[item['name']].value" placeholder="请选择">
              <el-option-group
                v-for="group in rule[item['ruleType']].concat(rule.custom)"
                :key="group.name"
                :label="group.name">
                <el-option
                  v-for="rule in group.children"
                  :key="rule.id"
                  :label="rule.itemName"
                  :value="rule.itemName">
                  <span style="float: left">{{ rule.itemName }}</span>
                  <span style="float: right; color: #8492a6; font-size: 13px">{{ rule.cnName }}</span>
                </el-option>
              </el-option-group>
            </el-select>
            <el-input class="mar-t-10" v-if="ruleMaps[item['name']].value.indexOf('Regular Expression Detection Count') > -1" v-model="ruleMaps[item['name']].regex" placeholder="请输入正则表达式"></el-input>
          </el-col>
        </el-row>
      </el-main>

      <el-main class="h-100p pad-lr-20" v-if="stepActive === 3">
        <configuration :model="sourceForm" :location="location" @save="getSrc"></configuration>
      </el-main>

      <el-main class="h-100p pad-lr-20" v-if="stepActive === 4">
        <el-form class="mar-t-20 pad-r-60" ref="model" :model="model" label-width="80px">
          <el-form-item label="名称" required>
            <el-input v-model="model.name"></el-input>
          </el-form-item>
          <el-form-item label="描述">
            <el-input v-model="model.description"></el-input>
          </el-form-item>
        </el-form>
      </el-main>

    </el-container>
    <el-row class="bor-t pad-t-20">
      <el-col :span="12">
        <el-button v-if="stepActive > 1" @click.stop="setStepActive(true)">上一步</el-button>
      </el-col>
      <el-col class="text-right" :span="12">
        <el-button v-if="stepActive < steps.length" class="mar-l-20" type="primary" @click.stop="setStepActive(false)">下一步</el-button>
        <el-button v-if="stepActive === steps.length" class="mar-l-20" type="primary" @click.stop="saveModel">保存</el-button>
      </el-col>
    </el-row>
  </div>
</template>
<script>
import { mapGetters } from "vuex";

import { griffinService } from '@/api/griffin';
import { GroupRule } from './group-rule';

import configuration from './configuration';

export default {
  components: {
    configuration: configuration
  },
  data(){
    return {
      rule: {
        default: [
          {
            name: '简单统计',
            children: [
              {id: 1, itemName: "Null Count", cnName: "空计数"},
              {id: 2, itemName: "Distinct Count", cnName: "区别计数"},
              {id: 11, itemName: "Empty Count", cnName: "空计数"}
            ]
          },
          {
            name: '统计摘要',
            children: [
              {id: 3, itemName: "Total Count", cnName: "总数"}
            ]
          },
          {
            name: '高级统计',
            children: [
              {id: 9, itemName: "Enum Detection Top5 Count", cnName: "枚举检测Top5计数"},
              {id: 10, itemName: "Regular Expression Detection Count", cnName: "正则表达式检测计数"}
            ]
          }
        ],
        isNum: [
          {
            name: '简单统计',
            children: [
              {id: 1, itemName: "Null Count", cnName: "空计数"},
              {id: 2, itemName: "Distinct Count", cnName: "区别计数"}
            ]
          },
          {
            name: '统计摘要',
            children: [
              {id: 3, itemName: "Total Count", cnName: "总数"},
              {id: 4, itemName: "Maximum", cnName: "最大"},
              {id: 5, itemName: "Minimum", cnName: "最小"},
              {id: 6, itemName: "Average", cnName: "平均"},
            ]
          },
          {
            name: '高级统计',
            children: [
              {id: 9, itemName: "Enum Detection Top5 Count", cnName: "枚举检测Top5计数"}
            ]
          }
        ],
        custom: [
          {
            name: '自定义',
            children: []
          }
        ]
      },
      customRules: {},
      stepActive: 1,
      saveLoading: false,
      treeLoading: false,
      tableLoading: false,
      steps: [],
      tableNamesData: [],
      tableData: [],
      location: '',
      treeSelect: '',
      selectDatabase: '',
      tableSelectData: [],
      ruleMaps: {

      },
      model: {
        'dq.type': 'PROFILING',
        'measure.type': 'griffin',
        'name': '',
        'owner': '',
        'description': '',
        'process.type': 'BATCH',
        'data.sources': [
          {
            'name': 'source',
            'connector': {}
          }
        ],
        'evaluate.rule': {
          "out.dataframe.name": "profiling",
          'rules': []
        },
        'rule.description': {
          'details': []
        }
      },
      sourceForm: null
    }
  },
  computed: mapGetters(['userInfo']),
  props: {
    measureType: {
      default: null,
      type: Object
    }
  },
  mounted(){
    this.model.owner = this.userInfo.account;
    this.steps = this.measureType.steps || [];
    this.getTableNames();
    griffinService.getFuncs().then(
      res => {
        let datalist = res.data.data || [];
        let customs = [];
        datalist.forEach(
          item => {
            customs.push({
              id: item.id,
              itemName: item.funcName,
              cnName: item.description
            })
            this.customRules[item.funcName] = {
              id: item.id,
              use: false,
              creates: []
            };
          }
        )
        this.rule.custom[0].children = customs;
      }
    )
  },
  methods: {
    getSrc(model){
      this.sourceForm = model;
    },
    getTableNames(){
      this.treeLoading = true;
      griffinService.getTableNames().then(
        res => {
          this.treeLoading = false;
          let tableNames = [];
          if(res.data){
            let data = res.data;
            Object.keys(data).forEach(
              keyName => {
                if(data[keyName].length){
                  let dbData = {
                    id: keyName,
                    label: keyName,
                    children: []
                  }
                  data[keyName].forEach(
                    item => {
                      dbData.children.push({
                        id: keyName + '.' + item,
                        label: item,
                        parent: keyName
                      })
                    }
                  )
                  tableNames.push(dbData);
                }
              }
            )
          }
          this.tableNamesData = tableNames;
        }
      ).catch(() => {
        this.getTableNames();
      })
    },
    ruleCahnge(){
      Object.values(this.customRules).forEach(
        item => {
          item.use = false;
        }
      )
      Object.keys(this.ruleMaps).forEach(
        key => {
          let item = this.ruleMaps[key];
          item.value.forEach(
            rule => {
              if(this.customRules[rule]){
                this.customRules[rule].use = true;
                if(!this.customRules[rule].creates.includes(key)){
                  griffinService.createHiveUdfFunc(this.selectDatabase , this.customRules[rule].id).then(
                    () => {
                      this.customRules[rule].creates.push(key);
                    }
                  );
                }
              }
            }
          )
        }
      )
    },
    checkCreate(){
      let result = true;
      Object.keys(this.ruleMaps).forEach(
        key => {
          let item = this.ruleMaps[key];
          item.value.forEach(
            rule => {
              if(this.customRules[rule]){
                if(!this.customRules[rule].creates.includes(key)){
                  result = false;
                  this.ruleCahnge();
                }
              }
            }
          )
        }
      )
      return result;
    },
    handleNodeClick(data){
      if(!data['children'] && data.parent){
        if(this.treeSelect === data.id){
          return;
        }
        this.treeSelect = data.label;
        this.selectDatabase = data.parent;
        let sources = this.model['data.sources'][0];
        let connector = {
          'config': {
            'database': data.parent,
            'table.name': data.label,
            'where': ''
          },
          'data.time.zone': '',
          'data.unit': '',
          'name': sources.name + new Date().getTime(),
          'type': 'HIVE',
          'version': '1.2'
        }
        this.model['data.sources'][0]['connector'] = connector;
        this.tableData = [];
        this.tableLoading = true;
        griffinService.getTableMetadata({
          db: data.parent,
          table: data.label
        }).then(
          res => {
            this.tableLoading = false;
            if(res.data.sd){
              this.location = res.data.sd.location || '';
              let datalist = res.data ? res.data.sd.cols : [];
              datalist.forEach(
                (item , index) => {
                  item['index'] = index;
                }
              )
              this.tableData = datalist;
            }
          }
        )
      }
    },
    handleSelectionChange(rows){
      this.tableSelectData = rows;
    },
    setStepActive(prev){
      if(prev && this.stepActive > 1){
        this.stepActive--;
      }
      if(prev === false && this.stepActive < this.steps.length){
        if(this.stepActive === 1){
          if(this.tableSelectData.length){
            let ruleMaps = {} , oldRuleMaps = this.ruleMaps;
            let patt = new RegExp("int|double|float/i");
            this.tableSelectData.forEach(
              item => {
                item['ruleType'] = 'default';
                if (patt.test(item.type)) {
                  item['ruleType'] = 'isNum';
                }
                ruleMaps[item.name] = oldRuleMaps[item.name] || {
                  value: [],
                  regex: '',
                  database: this.selectDatabase,
                  table: this.treeSelect
                }
              }
            )
            this.ruleMaps = ruleMaps;
            this.stepActive++;
          }else{
            this.$message({
              type: 'error',
              message: '请至少选择一个属性!'
            })
          }
        }else if(this.stepActive === 2){
          let nextStep = true;
          Object.values(this.ruleMaps).forEach(
            item => {
              if(item.value.length < 1){
                nextStep = false;
              }
            }
          )
          if(nextStep){
            this.stepActive++;
          }else{
            this.$message({
              type: 'error',
              message: '请完整填写表单!'
            })
          }
        }else{
          this.stepActive++;
        }
      }
    },
    
    saveModel(){
      if(!this.model.name){
        this.$message({
          type: 'error',
          message: '指标名称不能为空'
        });
        return false;
      }else{
        if(!this.$store.state.dag.projectId || !this.$store.state.dag.projectName){
          this.$message({
            type: 'error',
            message: '数据错误，请返回项目重新进入。'
          });
          return false;
        }
        let groupRules = new GroupRule(this.ruleMaps);
        this.model['evaluate.rule'].rules = groupRules.rules;
        this.model['rule.description'].details = groupRules.noderule;
  
        this.model['data.sources'][0]['connector']['config']['where'] = this.sourceForm.where;
        this.model['data.sources'][0]['connector']['data.unit'] = this.sourceForm['data.unit'];
        this.model['data.sources'][0]['connector']['data.time.zone'] = this.sourceForm['data.time.zone'];
  
        if(this.sourceForm['predicates']){
          this.model['data.sources'][0]['connector']['predicates'] = this.sourceForm['predicates'];
        }

        if(this.checkCreate()){
          this.saveLoading = true;
          griffinService.saveMeasures({
            ...this.model,
            'projectId': this.$store.state.dag.projectId,
            'projectName': this.$store.state.dag.projectName
          }).then(
            () => {
              this.saveLoading = false;
              this.$message({
                type: 'success',
                message: '保存成功'
              });
              this.$emit('back');
            }
          ).catch(() => {
            this.saveLoading = false;
          })
        }else{
          this.$message({
            type: 'error',
            message: '保存失败，请重新提交。'
          });
          return false;
        }
      }
    }
  }
}
</script>